/********************************************************************************
 * @file    app_udp.c
 * @brief   UDP服务器应用逻辑处理
 * 
 * @author  nzttj
 * @date    2025-03-12
 * @version 1.0
 * 
 * Copyright (C) 2025 nzttj
 * 
 * 本软件使用 GNU 通用公共许可证 (GPL) 第 3 版授权。
 * 
 * 您可以自由使用、修改、分发本软件，但必须遵守以下条件：
 * 1. 源代码必须开放，且您修改后的代码也必须以 GPL 许可证发布。
 * 2. 发布或分发本软件时，必须附带本许可证，并提供源代码或获取源代码的方式。
 * 
 * 本软件按"原样"提供，不附带任何担保，使用风险由用户自行承担。
 * 
 ********************************************************************************/

#include "app_udp.h"
#include "bl0942.h"
#include "app_iot_ctrl.h"
#include "app_energy_storage.h"
#include "smart_timer.h"
#include "app_wifi.h"
#include "app_mqtt.h"
#include "app_ota.h"
#include "app_nvs.h"

#include <string.h>
#include <sys/param.h>
#include "lwip/sockets.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "cJSON.h"

#define FRAME_HEAD  (0x55AA)
// 配置参数JSON字符串最大长度
#define CONFIG_JSON_MAX_LEN (1024)

// 命令处理函数返回值
typedef enum
{
    CMD_RET_SUCCESS = 0,   // 处理成功
    CMD_RET_INVALID_PARAM, // 无效参数
    CMD_RET_ERROR,         // 处理错误
} cmd_ret_t;

// 命令处理函数原型
typedef cmd_ret_t (*cmd_handler_t)(const uint8_t *data, uint16_t len, const struct sockaddr_in *peer_addr);

// 命令表项结构
typedef struct
{
    local_cmd_type_t cmd;          // 命令类型
    cmd_handler_t handler;   // 处理函数
    const char *description; // 命令描述
} cmd_table_item_t;

// 函数声明
static uint16_t _pack_frame(uint8_t *buffer, uint8_t cmd, const uint8_t *data, uint16_t data_len);
static cmd_ret_t _handle_query_electrical_data(const uint8_t *data, uint16_t len,
                                               const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_set_switch_state(const uint8_t *data, uint16_t len,
                                          const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_query_switch_state(const uint8_t *data, uint16_t len,
                                            const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_query_energy_storage_count(const uint8_t *data, uint16_t len,
                                                    const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_query_energy_storage_index_record(const uint8_t *data, uint16_t len,
                                                     const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_query_energy_storage_date_record(const uint8_t *data, uint16_t len,
                                                     const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_add_timer_event(const uint8_t *data, uint16_t len,
                                         const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_delete_timer_event(const uint8_t *data, uint16_t len,
                                            const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_query_timer_events(const uint8_t *data, uint16_t len,
                                            const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_update_timer_event(const uint8_t *data, uint16_t len,
                                            const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_factory_reset(const uint8_t *data, uint16_t len,
                                       const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_set_child_lock(const uint8_t *data, uint16_t len,
                                        const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_query_child_lock(const uint8_t *data, uint16_t len,
                                          const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_set_led_state(const uint8_t *data, uint16_t len,
                                       const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_query_led_state(const uint8_t *data, uint16_t len,
                                         const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_set_power_on_state(const uint8_t *data, uint16_t len,
                                            const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_query_power_on_state(const uint8_t *data, uint16_t len,
                                              const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_reboot(const uint8_t *data, uint16_t len,
                                const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_query_config(const uint8_t *data, uint16_t len,
                                      const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_set_config(const uint8_t *data, uint16_t len,
                                    const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_ota_update(const uint8_t *data, uint16_t len,
                                    const struct sockaddr_in *peer_addr);
static cmd_ret_t _handle_query_device_info(const uint8_t *data, uint16_t len,
                                           const struct sockaddr_in *peer_addr);

static const char *TAG = "app_udp";
static int s_udp_socket = -1;
static TaskHandle_t s_udp_task_handle = NULL;
static struct sockaddr_in s_client_addr;

// 命令表
static const cmd_table_item_t s_cmd_table[] = {
    {
        .cmd = CMD_QUERY_ELECTRICAL_DATA,
        .handler = _handle_query_electrical_data,
        .description = "查询当前电气参数"
    },
    {
        .cmd = CMD_SET_SWITCH_STATE,
        .handler = _handle_set_switch_state,
        .description = "设置开关状态"
    },
    {
        .cmd = CMD_QUERY_SWITCH_STATE,
        .handler = _handle_query_switch_state,
        .description = "查询开关状态"
    },
    {
        .cmd = CMD_QUERY_ENERGY_STORAGE_COUNT,
        .handler = _handle_query_energy_storage_count,
        .description = "查询能量存储记录总数"
    },
    {
        .cmd = CMD_QUERY_ENERGY_STORAGE_INDEX_RECORD,
        .handler = _handle_query_energy_storage_index_record,
        .description = "查询指定的能量存储记录"
    },
    {
        .cmd = CMD_QUERY_ENERGY_STORAGE_DATE_RECORD,
        .handler = _handle_query_energy_storage_date_record,
        .description = "查询指定日期能量存储记录"
    },
    {
        .cmd = CMD_ADD_TIMER_EVENT,
        .handler = _handle_add_timer_event,
        .description = "添加定时事件"
    },
    {
        .cmd = CMD_DELETE_TIMER_EVENT,
        .handler = _handle_delete_timer_event,
        .description = "删除定时事件"
    },
    {
        .cmd = CMD_QUERY_TIMER_EVENTS,
        .handler = _handle_query_timer_events,
        .description = "查询定时事件列表"
    },
    {
        .cmd = CMD_UPDATE_TIMER_EVENT,
        .handler = _handle_update_timer_event,
        .description = "更新定时事件"
    },
    {
        .cmd = CMD_SET_CHILD_LOCK,
        .handler = _handle_set_child_lock,
        .description = "设置儿童安全锁"
    },
    {
        .cmd = CMD_QUERY_CHILD_LOCK,
        .handler = _handle_query_child_lock,
        .description = "查询儿童安全锁状态"
    },
    {
        .cmd = CMD_SET_LED_STATE,
        .handler = _handle_set_led_state,
        .description = "设置LED状态"
    },
    {
        .cmd = CMD_QUERY_LED_STATE,
        .handler = _handle_query_led_state,
        .description = "查询LED状态"
    },
    {
        .cmd = CMD_SET_POWER_ON_STATE,
        .handler = _handle_set_power_on_state,
        .description = "设置断电后上电状态"
    },
    {
        .cmd = CMD_QUERY_POWER_ON_STATE,
        .handler = _handle_query_power_on_state,
        .description = "查询断电后上电状态"
    },
    {
        .cmd = CMD_QUERY_CONFIG,
        .handler = _handle_query_config,
        .description = "查询配置参数"
    },
    {
        .cmd = CMD_SET_CONFIG,
        .handler = _handle_set_config,
        .description = "设置配置参数"
    },
    {
        .cmd = CMD_OTA_UPDATE,
        .handler = _handle_ota_update,
        .description = "OTA升级"
    },
    {
        .cmd = CMD_QUERY_DEVICE_INFO,
        .handler = _handle_query_device_info,
        .description = "查询设备信息"
    },
    {
        .cmd = CMD_FACTORY_RESET,
        .handler = _handle_factory_reset,
        .description = "恢复出厂设置"
    },
    {
        .cmd = CMD_REBOOT,
        .handler = _handle_reboot,
        .description = "重启设备"
    }
    // 在此处添加新的命令项...
};

// 查询电气参数处理函数
static cmd_ret_t _handle_query_electrical_data(const uint8_t *data, uint16_t len,
                                               const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[64];
    electrical_data_t *electrical_data = bl0942_get_electrical_data();

    ESP_LOGI(TAG, "Query electrical data");

    // 打包响应数据
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_QUERY_ELECTRICAL_DATA,
                                     (uint8_t *)electrical_data,
                                     sizeof(electrical_data_t));

    // 直接发送响应
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 设置开关状态处理函数
static cmd_ret_t _handle_set_switch_state(const uint8_t *data, uint16_t len,
                                          const struct sockaddr_in *peer_addr)
{
    uint8_t switch_state = data[0];
    ESP_LOGI(TAG, "Set switch state: %d", switch_state);

    // 设置开关状态
    iot_ctrl_t iot_ctrl = {.type = IOT_CTRL_TYPE_CN8023A, .value = switch_state};
    app_iot_ctrl_with_queue(&iot_ctrl);

    return CMD_RET_SUCCESS;
}

static cmd_ret_t _handle_query_switch_state(const uint8_t *data, uint16_t len,
                                            const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[16];
    uint8_t switch_state = app_iot_ctrl_get_device_state()->led_on;

    ESP_LOGI(TAG, "Query switch state: %d", switch_state);

    // 打包响应数据
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_QUERY_SWITCH_STATE,
                                     (uint8_t *)&switch_state, sizeof(switch_state));

    // 直接发送响应
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 查询记录总数的处理函数
static cmd_ret_t _handle_query_energy_storage_count(const uint8_t *data, uint16_t len,
                                                    const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[16];
    uint16_t record_count;

    // 获取记录总数
    app_energy_storage_get_record_count(&record_count);

    ESP_LOGI(TAG, "Query energy storage count: %u", record_count);

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_QUERY_ENERGY_STORAGE_COUNT,
                                     (uint8_t *)&record_count, sizeof(record_count));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 查询指定索引记录的处理函数
static cmd_ret_t _handle_query_energy_storage_index_record(const uint8_t *data, uint16_t len,
                                                     const struct sockaddr_in *peer_addr)
{
    if (len < sizeof(uint16_t))
    {
        return CMD_RET_INVALID_PARAM;
    }

    uint8_t resp_buffer[64];
    uint16_t record_index = *(uint16_t *)data;
    energy_daily_record_t record;

    ESP_LOGI(TAG, "Query energy storage record index: %u", record_index);

    // 读取指定索引的记录
    if (app_energy_storage_read_record(record_index, &record) != STORAGE_OK)
    {
        return CMD_RET_ERROR;
    }

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_QUERY_ENERGY_STORAGE_INDEX_RECORD,
                                     (uint8_t *)&record, sizeof(record));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 查询指定日期记录的处理函数
static cmd_ret_t _handle_query_energy_storage_date_record(const uint8_t *data, uint16_t len,
                                                          const struct sockaddr_in *peer_addr)
{
    struct tm info = {0};
    energy_daily_record_t record;
    uint8_t resp_buffer[64];

    record.year = data[1] << 8 | data[0];
    record.month = data[2];
    record.day = data[3];

    info.tm_year = record.year + 2000 - 1900;
    info.tm_mon = record.month - 1;
    info.tm_mday = record.day;

    ESP_LOGI(TAG, "Query energy storage date record: %u-%u-%u", record.year, record.month, record.day);

    // 获取指定日期记录
    float energy_wh = 0.0f;
    app_energy_storage_get_energy(mktime(&info), &energy_wh);
    record.energy_x10 = (uint32_t)(energy_wh * 10);

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_QUERY_ENERGY_STORAGE_DATE_RECORD,
                                     (uint8_t *)&record, sizeof(record));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 添加定时事件处理函数
static cmd_ret_t _handle_add_timer_event(const uint8_t *data, uint16_t len,
                                         const struct sockaddr_in *peer_addr)
{
    ESP_LOGI(TAG, "Add timer event");

    if (len != sizeof(timer_add_cmd_t)) {
        ESP_LOGE(TAG, "Invalid data length: %d", len);
        return CMD_RET_INVALID_PARAM;
    }

    timer_add_cmd_t *cmd = (timer_add_cmd_t *)data;
    uint8_t timer_id;
    uint8_t resp_buffer[16];

    // 转换为定时器配置结构
    timer_config_t config = {
        .type = cmd->type,
        .action = cmd->action,
        .time = {
            .hour = cmd->hour,
            .minute = cmd->minute,
            .second = cmd->second,
            .day_mask = cmd->day_mask
        },
        .end_action = cmd->end_action,
        .end_time = {
            .hour = cmd->end_hour,
            .minute = cmd->end_minute,
            .second = cmd->end_second
        },
        .enabled = cmd->enabled
    };

    // 添加定时器
    timer_err_t err = smart_timer_add(&config, &timer_id);
    if (err != TIMER_OK) {
        ESP_LOGE(TAG, "Failed to add timer: %d", err);
        timer_id = 0;  // 使用0表示添加失败
    }

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_ADD_TIMER_EVENT, &timer_id, sizeof(timer_id));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 删除定时事件处理函数
static cmd_ret_t _handle_delete_timer_event(const uint8_t *data, uint16_t len,
                                            const struct sockaddr_in *peer_addr)
{
    ESP_LOGI(TAG, "Delete timer event");

    if (len != sizeof(timer_delete_cmd_t)) {
        ESP_LOGE(TAG, "Invalid data length: %d", len);
        return CMD_RET_INVALID_PARAM;
    }

    timer_delete_cmd_t *cmd = (timer_delete_cmd_t *)data;
    uint8_t resp_buffer[16];
    uint8_t success = 1;

    // 删除定时器
    timer_err_t err = smart_timer_delete(cmd->timer_id);
    if (err != TIMER_OK) {
        ESP_LOGE(TAG, "Failed to delete timer %d: %d", cmd->timer_id, err);
        success = 0;
    }

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_DELETE_TIMER_EVENT, &success, sizeof(success));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 查询定时事件列表处理函数
static cmd_ret_t _handle_query_timer_events(const uint8_t *data, uint16_t len,
                                            const struct sockaddr_in *peer_addr)
{
    ESP_LOGI(TAG, "Query timer events");

    uint8_t resp_buffer[512];  // 足够大的缓冲区以容纳多个定时器配置
    timer_config_t timers[32];
    uint8_t count = 32;
    timer_add_cmd_t simple_timers[32];  // 定时器配置数组

    // 获取定时器列表
    timer_err_t err = smart_timer_get_list(timers, &count);
    if (err != TIMER_OK) {
        ESP_LOGE(TAG, "Failed to get timer list: %d", err);
        count = 0;
    }

    // 转换为简化的格式
    for (int i = 0; i < count; i++) {
        simple_timers[i].type = timers[i].type;
        simple_timers[i].action = timers[i].action;
        simple_timers[i].hour = timers[i].time.hour;
        simple_timers[i].minute = timers[i].time.minute;
        simple_timers[i].second = timers[i].time.second;
        simple_timers[i].day_mask = timers[i].time.day_mask;
        simple_timers[i].end_action = timers[i].end_action;
        simple_timers[i].end_hour = timers[i].end_time.hour;
        simple_timers[i].end_minute = timers[i].end_time.minute;
        simple_timers[i].end_second = timers[i].end_time.second;
        simple_timers[i].enabled = timers[i].enabled;
    }

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_QUERY_TIMER_EVENTS,
                                     (uint8_t *)simple_timers, count * sizeof(timer_add_cmd_t));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 更新定时事件处理函数
static cmd_ret_t _handle_update_timer_event(const uint8_t *data, uint16_t len,
                                            const struct sockaddr_in *peer_addr)
{
    ESP_LOGI(TAG, "Update timer event");

    if (len != sizeof(timer_update_cmd_t)) {
        ESP_LOGE(TAG, "Invalid data length: %d", len);
        return CMD_RET_INVALID_PARAM;
    }

    timer_update_cmd_t *cmd = (timer_update_cmd_t *)data;
    uint8_t resp_buffer[16];
    uint8_t success = 1;

    // 转换为定时器配置结构
    timer_config_t config = {
        .id = cmd->timer_id,
        .type = cmd->config.type,
        .action = cmd->config.action,
        .time = {
            .hour = cmd->config.hour,
            .minute = cmd->config.minute,
            .second = cmd->config.second,
            .day_mask = cmd->config.day_mask
        },
        .end_action = cmd->config.end_action,
        .end_time = {
            .hour = cmd->config.end_hour,
            .minute = cmd->config.end_minute,
            .second = cmd->config.end_second
        },
        .enabled = cmd->config.enabled
    };

    // 更新定时器配置
    timer_err_t err = smart_timer_update(&config);
    if (err != TIMER_OK) {
        ESP_LOGE(TAG, "Failed to update timer %d: %d", cmd->timer_id, err);
        success = 0;
    }

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_UPDATE_TIMER_EVENT, &success, sizeof(success));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 实现恢复出厂设置处理函数
static cmd_ret_t _handle_factory_reset(const uint8_t *data, uint16_t len,
                                      const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[16];
    uint8_t success = 1;

    ESP_LOGI(TAG, "Executing factory reset...");

    // 执行恢复出厂设置操作
    // 1. 清除定时器事件
    
    // 2. 清除能量存储记录
    app_energy_storage_delete_all_records();

    // 打包响应数据
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_FACTORY_RESET,
                                    &success, sizeof(success));

    // 发送响应
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 设置儿童安全锁处理函数
static cmd_ret_t _handle_set_child_lock(const uint8_t *data, uint16_t len,
                                        const struct sockaddr_in *peer_addr)
{
    if (len != sizeof(uint8_t)) {
        ESP_LOGE(TAG, "Invalid data length: %d", len);
        return CMD_RET_INVALID_PARAM;
    }

    uint8_t lock_state = data[0];
    uint8_t resp_buffer[16];
    uint8_t success = 1;

    ESP_LOGI(TAG, "Set child lock state: %u", lock_state);

    // 设置儿童安全锁状态
    if (app_iot_ctrl_set_child_lock(lock_state) != 0) {
        ESP_LOGE(TAG, "Failed to set child lock state");
        success = 0;
    }

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_SET_CHILD_LOCK, &success, sizeof(success));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 查询儿童安全锁状态处理函数
static cmd_ret_t _handle_query_child_lock(const uint8_t *data, uint16_t len,
                                          const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[16];
    uint8_t lock_state = app_iot_ctrl_get_device_state()->child_lock;

    ESP_LOGI(TAG, "Query child lock state: %u", lock_state);

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_QUERY_CHILD_LOCK, &lock_state, sizeof(lock_state));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 设置LED状态处理函数
static cmd_ret_t _handle_set_led_state(const uint8_t *data, uint16_t len,
                                      const struct sockaddr_in *peer_addr)
{
    if (len != sizeof(uint8_t)) {
        ESP_LOGE(TAG, "Invalid data length: %d", len);
        return CMD_RET_INVALID_PARAM;
    }

    uint8_t resp_buffer[16];
    uint8_t success = 1;

    ESP_LOGI(TAG, "Set led state: %u", data[0]);

    // 设置LED状态
    if (app_iot_ctrl_set_led_state(data[0]) != 0) {
        ESP_LOGE(TAG, "Failed to set LED state");
        success = 0;
    }

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_SET_LED_STATE, &success, sizeof(success));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 查询LED状态处理函数
static cmd_ret_t _handle_query_led_state(const uint8_t *data, uint16_t len,
                                         const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[16];
    uint8_t led_state = app_iot_ctrl_get_device_state()->led_enabled;

    ESP_LOGI(TAG, "Query LED state: %u", led_state);

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_QUERY_LED_STATE, &led_state, sizeof(led_state));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 设置断电后上电状态处理函数
static cmd_ret_t _handle_set_power_on_state(const uint8_t *data, uint16_t len,
                                           const struct sockaddr_in *peer_addr)
{
    if (len != sizeof(uint8_t)) {
        ESP_LOGE(TAG, "Invalid data length: %d", len);
        return CMD_RET_INVALID_PARAM;
    }

    uint8_t resp_buffer[16];
    uint8_t success = 1;

    ESP_LOGI(TAG, "Set power on state: %u", data[0]);

    // 设置断电后上电状态
    if (app_iot_ctrl_set_power_on_state(data[0]) != 0) {
        ESP_LOGE(TAG, "Failed to set power on state");
        success = 0;
    }

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_SET_POWER_ON_STATE, &success, sizeof(success));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 查询断电后上电状态处理函数
static cmd_ret_t _handle_query_power_on_state(const uint8_t *data, uint16_t len,
                                             const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[16];
    uint8_t power_on_state = app_iot_ctrl_get_power_on_state();

    ESP_LOGI(TAG, "Query power on state: %u", power_on_state);

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_QUERY_POWER_ON_STATE, &power_on_state, sizeof(power_on_state));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    return CMD_RET_SUCCESS;
}

// 重启设备处理函数
static cmd_ret_t _handle_reboot(const uint8_t *data, uint16_t len,
                                const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[16];
    uint8_t success = 1;

    ESP_LOGI(TAG, "Rebooting device...");

    // 打包响应数据
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_REBOOT,
                                     &success, sizeof(success));
    // 发送响应
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    vTaskDelay(pdMS_TO_TICKS(1000));
    esp_restart();

    return CMD_RET_SUCCESS;
}

// 查询配置参数处理函数
static cmd_ret_t _handle_query_config(const uint8_t *data, uint16_t len,
                                     const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[CONFIG_JSON_MAX_LEN];
    cJSON *root = cJSON_CreateObject();

    ESP_LOGI(TAG, "Query config parameters");

    // 获取WiFi配置
    app_wifi_info_t *wifi_info = app_wifi_get_info();
    cJSON_AddStringToObject(root, "ssid", wifi_info->conn_info.ssid);
    cJSON_AddStringToObject(root, "pwd", wifi_info->conn_info.pwd);

    // 获取MQTT配置
    app_mqtt_info_t *mqtt_info = app_mqtt_get_info();
    cJSON_AddStringToObject(root, "mqtt_url", mqtt_info->cfg.url);
    cJSON_AddStringToObject(root, "mqtt_username", mqtt_info->cfg.username);
    cJSON_AddStringToObject(root, "mqtt_pwd", mqtt_info->cfg.password);
    cJSON_AddStringToObject(root, "mqtt_down_topic", mqtt_info->topic.set_topic);
    cJSON_AddStringToObject(root, "mqtt_up_topic", mqtt_info->topic.report_topic);
    cJSON_AddStringToObject(root, "mqtt_ota_topic", mqtt_info->topic.ota_topic);
    cJSON_AddStringToObject(root, "mqtt_client_id", mqtt_info->cfg.client_id);

    // 获取OTA服务器配置
    app_ota_server_config_t *ota_server_cfg = app_ota_get_server_cfg();
    cJSON_AddStringToObject(root, "ota_server_url", ota_server_cfg->url);

    // 转换为JSON字符串
    char *json_str = cJSON_PrintUnformatted(root);
    cJSON_Delete(root);

    // 打包并发送响应
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_QUERY_CONFIG,
                                    (uint8_t *)json_str, strlen(json_str));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    free(json_str);
    return CMD_RET_SUCCESS;
}

// 设置配置参数处理函数
static cmd_ret_t _handle_set_config(const uint8_t *data, uint16_t len,
                                   const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[16];
    uint8_t success = 1;
    uint16_t frame_len;
    bool wifi_changed = false;
    bool mqtt_changed = false;

    ESP_LOGI(TAG, "Set config parameters");

    // 解析JSON数据
    cJSON *root = cJSON_Parse((char *)data);
    if (root == NULL) {
        ESP_LOGE(TAG, "Failed to parse JSON data");
        success = 0;
        goto end;
    }

    ESP_LOGI(TAG, "root: %s", cJSON_PrintUnformatted(root));

    // 设置WiFi配置
    app_wifi_info_t temp_wifi_info = {0};
    cJSON *ssid = cJSON_GetObjectItem(root, "ssid");
    cJSON *pwd = cJSON_GetObjectItem(root, "pwd");
    if (cJSON_IsString(ssid) && cJSON_IsString(pwd)) {
        strncpy(temp_wifi_info.conn_info.ssid, ssid->valuestring, sizeof(temp_wifi_info.conn_info.ssid) - 1);
        strncpy(temp_wifi_info.conn_info.pwd, pwd->valuestring, sizeof(temp_wifi_info.conn_info.pwd) - 1);
    }

    // 设置MQTT配置
    app_mqtt_info_t temp_mqtt_info = {0};
    cJSON *mqtt_url = cJSON_GetObjectItem(root, "mqtt_url");
    cJSON *mqtt_username = cJSON_GetObjectItem(root, "mqtt_username");
    cJSON *mqtt_pwd = cJSON_GetObjectItem(root, "mqtt_pwd");
    cJSON *mqtt_down_topic = cJSON_GetObjectItem(root, "mqtt_down_topic");
    cJSON *mqtt_up_topic = cJSON_GetObjectItem(root, "mqtt_up_topic");
    cJSON *mqtt_ota_topic = cJSON_GetObjectItem(root, "mqtt_ota_topic");
    cJSON *mqtt_client_id = cJSON_GetObjectItem(root, "mqtt_client_id");

    if (cJSON_IsString(mqtt_url) && cJSON_IsString(mqtt_username) && cJSON_IsString(mqtt_pwd) && cJSON_IsString(mqtt_down_topic) && cJSON_IsString(mqtt_up_topic) && cJSON_IsString(mqtt_ota_topic) && cJSON_IsString(mqtt_client_id)) {
        strncpy(temp_mqtt_info.cfg.url, mqtt_url->valuestring, sizeof(temp_mqtt_info.cfg.url) - 1);
        strncpy(temp_mqtt_info.cfg.username, mqtt_username->valuestring, sizeof(temp_mqtt_info.cfg.username) - 1);
        strncpy(temp_mqtt_info.cfg.password, mqtt_pwd->valuestring, sizeof(temp_mqtt_info.cfg.password) - 1);
        strncpy(temp_mqtt_info.topic.set_topic, mqtt_down_topic->valuestring, sizeof(temp_mqtt_info.topic.set_topic) - 1);
        strncpy(temp_mqtt_info.topic.report_topic, mqtt_up_topic->valuestring, sizeof(temp_mqtt_info.topic.report_topic) - 1);
        strncpy(temp_mqtt_info.topic.ota_topic, mqtt_ota_topic->valuestring, sizeof(temp_mqtt_info.topic.ota_topic) - 1);
        strncpy(temp_mqtt_info.cfg.client_id, mqtt_client_id->valuestring, sizeof(temp_mqtt_info.cfg.client_id) - 1);
    }

    // 设置OTA服务器配置
    app_ota_server_config_t temp_ota_server_cfg = {0};
    cJSON *ota_server_url = cJSON_GetObjectItem(root, "ota_server_url");
    if (cJSON_IsString(ota_server_url)) {
        strncpy(temp_ota_server_cfg.url, ota_server_url->valuestring, sizeof(temp_ota_server_cfg.url) - 1);
    }

    // 保存配置
    app_wifi_info_t *wifi_info = app_wifi_get_info();
    if (strcmp(wifi_info->conn_info.ssid, temp_wifi_info.conn_info.ssid) != 0 ||
        strcmp(wifi_info->conn_info.pwd, temp_wifi_info.conn_info.pwd) != 0) {
        memcpy(&wifi_info->conn_info, &temp_wifi_info.conn_info, sizeof(wifi_info->conn_info));
        app_nvs_save_wifi_sta_info(wifi_info);
        wifi_changed = true;
    }

    app_mqtt_info_t *mqtt_info = app_mqtt_get_info();
    if (strcmp(mqtt_info->cfg.url, temp_mqtt_info.cfg.url) != 0 ||
        strcmp(mqtt_info->cfg.username, temp_mqtt_info.cfg.username) != 0 ||
        strcmp(mqtt_info->cfg.password, temp_mqtt_info.cfg.password) != 0 ||
        strcmp(mqtt_info->cfg.client_id, temp_mqtt_info.cfg.client_id) != 0) {
        memcpy(&mqtt_info->cfg, &temp_mqtt_info.cfg, sizeof(mqtt_info->cfg));
        app_nvs_save_mqtt_cfg(&mqtt_info->cfg);
        mqtt_changed = true;
    }
    if (strcmp(mqtt_info->topic.set_topic, temp_mqtt_info.topic.set_topic) != 0 ||
        strcmp(mqtt_info->topic.report_topic, temp_mqtt_info.topic.report_topic) != 0 ||
        strcmp(mqtt_info->topic.ota_topic, temp_mqtt_info.topic.ota_topic) != 0) {
        memcpy(&mqtt_info->topic, &temp_mqtt_info.topic, sizeof(mqtt_info->topic));
        app_nvs_save_mqtt_topic(&mqtt_info->topic);
        mqtt_changed = true;
    }

    app_ota_server_config_t *ota_server_cfg = app_ota_get_server_cfg();
    if (strcmp(ota_server_cfg->url, temp_ota_server_cfg.url) != 0) {
        memcpy(ota_server_cfg->url, temp_ota_server_cfg.url, sizeof(ota_server_cfg->url));
        app_nvs_save_ota_server_cfg(ota_server_cfg);
    }

end:
    // 打包并发送响应
    frame_len = _pack_frame(resp_buffer, CMD_SET_CONFIG, &success, sizeof(success));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    if (root) {
        cJSON_Delete(root);
    }

    if (mqtt_changed) {
        ESP_LOGI(TAG, "MQTT config changed, reconnecting...");
        app_mqtt_deinit();
        app_mqtt_init();
    }
    if (wifi_changed) {
        vTaskDelay(pdMS_TO_TICKS(200)); // 等待udp消息发送完成
        ESP_LOGI(TAG, "WiFi config changed, reconnecting...");
        app_wifi_connect_to_new_ap(wifi_info->conn_info.ssid, wifi_info->conn_info.pwd);
    }

    return CMD_RET_SUCCESS;
}

// OTA升级处理函数
static cmd_ret_t _handle_ota_update(const uint8_t *data, uint16_t len,
                                   const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[16];
    uint8_t success = 1;
    uint16_t frame_len;

    ESP_LOGI(TAG, "Start OTA update");

    // 解析JSON数据
    cJSON *root = cJSON_Parse((char *)data);
    if (root == NULL) {
        ESP_LOGE(TAG, "Failed to parse JSON data");
        success = 0;
        goto end;
    }

    // 获取OTA URL
    cJSON *ota_url = cJSON_GetObjectItem(root, "ota_url");
    if (!cJSON_IsString(ota_url)) {
        ESP_LOGE(TAG, "Invalid OTA URL");
        success = 0;
        goto end;
    }

    // 设置OTA URL并开始升级
    app_ota_config_t cfg = {0};
    strncpy(cfg.url, ota_url->valuestring, sizeof(cfg.url) - 1);
    if (app_ota_init(&cfg) != 0) {
        ESP_LOGE(TAG, "Failed to start OTA update");
        success = 0;
    }

end:
    // 打包并发送响应
    frame_len = _pack_frame(resp_buffer, CMD_OTA_UPDATE, &success, sizeof(success));
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    if (root) {
        cJSON_Delete(root);
    }

    return CMD_RET_SUCCESS;
}

// 查询设备信息处理函数
static cmd_ret_t _handle_query_device_info(const uint8_t *data, uint16_t len,
                                          const struct sockaddr_in *peer_addr)
{
    uint8_t resp_buffer[256];
    cJSON *root = cJSON_CreateObject();
    uint8_t mac[6];
    char mac_str[18];

    // 获取MAC地址
    esp_wifi_get_mac(ESP_IF_WIFI_STA, mac);
    snprintf(mac_str, sizeof(mac_str), "%02X:%02X:%02X:%02X:%02X:%02X",
             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

    // 构建JSON响应
    cJSON_AddStringToObject(root, "mac", mac_str);
    cJSON_AddStringToObject(root, "version", PROJECT_VER);

    // 将JSON转换为字符串
    char *json_str = cJSON_PrintUnformatted(root);
    if (json_str == NULL) {
        cJSON_Delete(root);
        return CMD_RET_ERROR;
    }

    // 打包响应数据
    uint16_t frame_len = _pack_frame(resp_buffer, CMD_QUERY_DEVICE_INFO,
                                    (uint8_t *)json_str, strlen(json_str));

    // 发送响应
    sendto(s_udp_socket, resp_buffer, frame_len, 0,
           (struct sockaddr *)peer_addr, sizeof(struct sockaddr_in));

    // 释放资源
    free(json_str);
    cJSON_Delete(root);

    return CMD_RET_SUCCESS;
}

static cmd_handler_t _find_cmd_handler(local_cmd_type_t cmd)
{
    for (int i = 0; i < sizeof(s_cmd_table) / sizeof(s_cmd_table[0]); i++)
    {
        if (s_cmd_table[i].cmd == cmd)
        {
            return s_cmd_table[i].handler;
        }
    }
    return NULL;
}

/**
 * @brief CRC16 计算（MODBUS）
 * 
 * @param data 数据
 * @param len 数据长度
 * @return CRC16 值
 */
static inline uint16_t _crc16_modbus(const uint8_t *data, uint16_t len)
{
    uint16_t crc = 0xFFFF;
    for (uint16_t i = 0; i < len; i++)
    {
        crc ^= data[i];
        for (uint8_t j = 0; j < 8; j++)
        {
            if (crc & 1)
            {
                crc = (crc >> 1) ^ 0xA001;
            }
            else
            {
                crc >>= 1;
            }
        }
    }
    return crc;
}

/**
 * @brief 组帧
 * 
 * @param buffer 缓冲区
 * @param cmd 指令
 * @param data 数据
 * @param data_len 数据长度
 * @return 帧长
 */
static uint16_t _pack_frame(uint8_t *buffer, uint8_t cmd, const uint8_t *data, uint16_t data_len)
{
    uint16_t offset = 0;
    // 帧头
    buffer[offset++] = (FRAME_HEAD >> 8) & 0xFF;
    buffer[offset++] = FRAME_HEAD & 0xFF;

    // 数据长度
    buffer[offset++] = (data_len >> 8) & 0xFF;
    buffer[offset++] = data_len & 0xFF;

    // 指令
    buffer[offset++] = cmd;

    // 数据
    if (data_len > 0 && data != NULL)
    {
        memcpy(&buffer[offset], data, data_len);
        offset += data_len;
    }

    // CRC16
    uint16_t crc = _crc16_modbus(buffer, offset);
    buffer[offset++] = crc & 0xFF;
    buffer[offset++] = (crc >> 8) & 0xFF;

    return offset; // 返回总帧长
}

/**
 * @brief 解帧
 * 
 * @param buffer 缓冲区
 * @param length 长度
 * @param cmd 指令
 * @param data 数据
 * @param data_len 数据长度
 * @return 0 on success, other on failure
 */
static int _unpack_frame(const uint8_t *buffer, uint16_t length, uint8_t *cmd, uint8_t *data, uint16_t *data_len)
{
    if (length < 7)
        return -1; // 长度不足

    // 检查帧头
    if ((buffer[0] << 8 | buffer[1]) != FRAME_HEAD)
        return -2;

    // 获取数据长度
    *data_len = (buffer[2] << 8) | buffer[3];
    if (*data_len + 7 != length)
        return -3; // 长度不匹配

    // 校验 CRC
    uint16_t crc_recv = (buffer[length - 1] << 8) | buffer[length - 2];
    if (_crc16_modbus(buffer, length - 2) != crc_recv)
        return -4;

    // 获取指令
    *cmd = buffer[4];

    // 复制数据
    if (*data_len > 0)
    {
        memcpy(data, &buffer[5], *data_len);
    }

    return 0;
}

/**
 * @brief UDP服务器任务
 */
static void _udp_server_task(void *param)
{
    struct sockaddr_in server_addr;
    char rx_buffer[512];
    socklen_t addr_len = sizeof(s_client_addr);

    // 1. 创建UDP套接字
    s_udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (s_udp_socket < 0) {
        ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
        vTaskDelete(NULL);
    }

    // 2. 绑定IP和端口
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(APP_UDP_PORT);
    if (bind(s_udp_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        ESP_LOGE(TAG, "Socket bind failed: errno %d", errno);
        close(s_udp_socket);
        vTaskDelete(NULL);
    }

    ESP_LOGI(TAG, "UDP server started, listening on port: %d", APP_UDP_PORT);

    for (;;)
    {
        // 接收数据
        int len = recvfrom(s_udp_socket, rx_buffer, sizeof(rx_buffer) - 1, 0,
                           (struct sockaddr *)&s_client_addr, &addr_len);

        if (len < 0)
        {
            ESP_LOGE(TAG, "Receive error: errno %d", errno);
            continue;
        }

        uint8_t cmd;
        uint16_t data_len;
        // 解析收到的数据帧
        if (_unpack_frame((const uint8_t *)rx_buffer, len, &cmd, (uint8_t *)rx_buffer, &data_len) == 0)
        {
            // 查找并执行命令处理函数
            cmd_handler_t handler = _find_cmd_handler(cmd);
            if (handler != NULL)
            {
                cmd_ret_t ret = handler((const uint8_t *)rx_buffer, data_len, &s_client_addr);
                if (ret != CMD_RET_SUCCESS)
                {
                    ESP_LOGW(TAG, "Command processing failed: cmd=0x%02X, ret=%d", cmd, ret);
                }
            }
            else
            {
                ESP_LOGW(TAG, "Unknown command: 0x%02X", cmd);
            }
        }
        else
        {
            ESP_LOGW(TAG, "Data frame parse failed");
        }
    }
}

int app_udp_send(const char *data, int len, const char *ip, int port)
{
    if (s_udp_socket < 0)
    {
        ESP_LOGE(TAG, "Socket not initialized");
        return -1;
    }

    struct sockaddr_in dest_addr;
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(port);
    inet_aton(ip, &dest_addr.sin_addr);

    return sendto(s_udp_socket, data, len, 0,
                  (struct sockaddr *)&dest_addr, sizeof(dest_addr));
}

int app_udp_package_send(local_cmd_type_t cmd, const uint8_t *data, uint16_t data_len)
{
    uint8_t buffer[128];
    uint16_t frame_len = _pack_frame(buffer, cmd, data, data_len);
    return sendto(s_udp_socket, buffer, frame_len, 0,
                  (struct sockaddr *)&s_client_addr, sizeof(s_client_addr));
}

int app_udp_init(void)
{
    if (s_udp_task_handle != NULL)
    {
        ESP_LOGW(TAG, "UDP server already initialized");
        return 0;
    }

    return xTaskCreate(_udp_server_task, "udp_server", 4096, NULL, 5, &s_udp_task_handle) == pdPASS ? 0 : -1;
}
